package role

import (
	"cgs-server/server"
	"cgs-server/server/base"
	"cgs-server/server/model"
	"errors"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

type RoleRepository interface {
	base.Repository
	// 根据 多个角色id 查询角色列表
	ListByIds(ids []primitive.ObjectID, mdl *model.DataUserModel) (*model.Roles, error)
	// 根据角色英文名称查询一个角色 (某个租户下的角色)
	FindByRoleAliasOrName(mdl *model.DataUserModel) (*model.Role, error)
	// 根据角色 id 查询
	GetById(mdl *model.DataUserModel) (*model.Role, error)
	// 根据角色id查询用户数量
	CountUser(roleId string) (int64, error)
	// 根据用户 id 数组查询用户
	FindUserByIds(ids []*primitive.ObjectID) ([]*model.SimpleUser, error)
	// 根据 visualId 获取应用
	FindVisualByVisualId(visualId primitive.ObjectID, visualType string) (*model.Visual, error)
}

func NewRoleRepository() RoleRepository {
	return &roleRepository{base.RepositoryStruct{
		CollectionName: server.RoleCollectionName,
	}}
}

type roleRepository struct {
	base.RepositoryStruct
}

func (r *roleRepository) Insert(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return err
		}
		role.ResolveEntity(role, mdl.User)
		_, err := r.Mongo.InsertOne(r.CollectionName, role)
		return err
	} else {
		return errors.New("Role type error")
	}

}

func (r *roleRepository) ListByIds(ids []primitive.ObjectID, mdl *model.DataUserModel) (*model.Roles, error) {
	if mdl == nil {
		return nil, errors.New("mdl is nil")
	}
	if err := r.CheckDB(); err != nil {
		return nil, err
	}
	var roles = &model.Roles{}
	filter := bson.M{
		"ID": bson.M{
			"$in": ids,
		},
	}
	if role, ok := mdl.Data.(*model.Role); ok {
		role.ResolveFilter(role, mdl.User, &filter)
		err := r.Mongo.FindMany(r.CollectionName, filter, roles)
		return roles, err
	}

	return nil, errors.New("mdl.Data should be *model.Role type")
}

func (r *roleRepository) FindByRoleAliasOrName(mdl *model.DataUserModel) (*model.Role, error) {
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return nil, err
		}
		filter := bson.M{
			"roleAlias": role.RoleAlias,
		}
		if role.VisualId != "" {
			filter["visualId"] = role.VisualId
		}
		/*if role.RoleAlias != "" {
			filter["roleAlias"] = role.RoleAlias
		} else if role.RoleName != "" {
			filter["Name"] = role.RoleName
		}*/
		if mdl.Filter != nil {
			filter = *mdl.Filter
		}
		role.ResolveFilter(role, mdl.User, &filter)
		result := &model.Role{}
		find, err := r.Mongo.FindOne(r.CollectionName, filter, result)
		if err != nil {
			return nil, err
		}
		if !find {
			return nil, nil
		}
		return result, nil
	}

	return nil, errors.New("Type of mdl.Data has error")
}

func (r *roleRepository) GetById(mdl *model.DataUserModel) (*model.Role, error) {
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return nil, err
		}
		filter := bson.M{
			"ID": role.Id,
		}
		role.ResolveFilter(role, mdl.User, &filter)
		result := &model.Role{}
		find, err := r.Mongo.FindOne(r.CollectionName, filter, result)
		if find {
			return result, nil
		}
		return nil, err
	} else {
		return nil, errors.New("Role type error")
	}
}

func (r *roleRepository) Find(mdl *model.DataUserModel) (interface{}, error) {
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return nil, err
		}
		filter := bson.M{
			"type": role.Type,
		}
		if role.VisualId != "" {
			filter["visualId"] = role.VisualId
		}
		role.ResolveFilter(role, mdl.User, &filter) // tenantId
		result := &model.Roles{}
		err := r.Mongo.FindMany(r.CollectionName, filter, result)
		return result, err
	} else {
		return nil, errors.New("Role type error")
	}
}

func (r *roleRepository) Update(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return err
		}
		filter := bson.M{
			"ID": role.Id,
		}
		role.ResolveFilter(role, mdl.User, &filter)
		updateOpts := bson.M{}
		if role.RoleName != "" {
			updateOpts["Name"] = role.RoleName
		}
		if role.ParentId != "" {
			updateOpts["parentId"] = role.ParentId
		}
		if role.Sort != nil {
			updateOpts["sort"] = role.Sort
		}
		if role.FormAuthType != nil {
			updateOpts["formAuthType"] = role.FormAuthType
		}
		if role.Desc != "" {
			updateOpts["desc"] = role.Desc
		}
		/*if role.UserSize > 0 {
			updateOpts["userSize"] = role.UserSize
		}*/
		role.ResolveUpdateCondition(role, mdl.User, &updateOpts)
		update := bson.M{
			"$set": updateOpts,
		}
		_, err := r.Mongo.UpdateOne(r.CollectionName, filter, update)
		return err
	} else {
		return errors.New("Role type error")
	}
}

func (r *roleRepository) DeleteLogic(mdl *model.DataUserModel) error {
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return err
		}
		filter := bson.M{
			"ID": role.Id,
		}
		role.ResolveFilter(role, mdl.User, &filter)
		updateOpts := bson.M{}
		role.DeleteLogic(role, mdl.User, &updateOpts)
		update := bson.M{
			"$set": updateOpts,
		}
		_, err := r.Mongo.UpdateOne(r.CollectionName, filter, update)
		return err
	} else {
		return errors.New("Role type error")
	}
}

func (r *roleRepository) Delete(mdl *model.DataUserModel) error {
	// 真实删除角色
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return err
		}
		filter := bson.M{
			"ID": role.Id,
		}
		//role.ResolveFilter(role, mdl.User, &filter)
		if mdl.Filter != nil {
			filter = *mdl.Filter
		}
		_, err := r.Mongo.DeleteOne(r.CollectionName, filter)
		return err
	} else {
		return errors.New("Role type error")
	}
}

func (r *roleRepository) CountUser(roleId string) (int64, error) {
	if err := r.InitDB(); err != nil {
		return 0, err
	}
	filter := bson.M{
		"RoleID": roleId,
	}
	return r.Mongo.Count(server.UserCollectionName, filter)
}

func (r *roleRepository) FindUserByIds(ids []*primitive.ObjectID) ([]*model.SimpleUser, error) {
	if ids == nil {
		return nil, errors.New("Ids is nil")
	}
	if err := r.InitDB(); err != nil {
		return nil, err
	}
	filter := bson.M{
		"ID": bson.M{
			"$in": ids,
		},
	}
	result := []*model.SimpleUser{}
	err := r.Mongo.FindMany(server.UserCollectionName, filter, &result)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (r *roleRepository) FindVisualByVisualId(visualId primitive.ObjectID, visualType string) (*model.Visual, error) {
	if err := r.InitDB(); err != nil {
		return nil, err
	}
	filter := bson.M{
		"ID": visualId,
	}
	result := &model.Visual{}
	find, err := r.Mongo.FindOne(server.CgsPortalVisualCollectionName+visualType, filter, result)
	if err != nil {
		return nil, err
	}
	if !find {
		return nil, nil
	}
	return result, nil
}

// 批量删除角色
func (r *roleRepository) BatchDelete(mdl *model.DataUserModel) error {
	// 真实删除角色
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return err
		}
		filter := bson.M{
			"ID": role.Id,
		}
		//role.ResolveFilter(role, mdl.User, &filter)
		if mdl.Filter != nil {
			filter = *mdl.Filter
		}
		_, err := r.Mongo.DeleteMany(r.CollectionName, filter)
		return err
	} else {
		return errors.New("Role type error")
	}
}

func (r *roleRepository) FindOne(mdl *model.DataUserModel) (interface{}, error) {
	if role, ok := mdl.Data.(*model.Role); ok {
		if err := r.CheckDB(); err != nil {
			return nil, err
		}
		filter := bson.M{
			"ID": role.Id,
		}
		//role.ResolveFilter(role, mdl.User, &filter)
		if mdl.Filter != nil {
			filter = *mdl.Filter
		}
		result := &model.Role{}
		find, err := r.Mongo.FindOne(r.CollectionName, filter, result)
		if find {
			return result, nil
		}
		return nil, err
	} else {
		return nil, errors.New("Role type error")
	}
}
